/*********************************************************
          File Name:reference_collapsing.cpp
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sat 19 Dec 2015 09:35:41 PM CST
**********************************************************/

#include <iostream>

using namespace std;

int foo(int &&x)
{
        return x;
}

template<typename T>
auto bar(T &&x) -> typename std::remove_reference<decltype(x)>::type
{
        T tmp = x;
        x += 1;
        return x;
}

int main()
{
        int j = 1;
        // illegal
        //cout << foo(j) << endl;
        // legal
        cout << foo(move(j)) << endl;

        // exception    Cppp p609
        // 1. passing a left value, template will instantiate to
        // `int bar<int&>(int& &&)`(invalid code)
        cout << bar(j) << endl;
        // 2. passing a right value, template will instantiate to
        // `int bar<int&&>(int&& &&)`(invalid code)
        cout << bar(1) << endl;

        // the following code demonstrate why right reference template `T&&`
        // is BAD!
        //
        // if we pass different types( right / left ) we get different result
        // and this is very difficult to write correct code!!
        int a = 1;
        if(bar(a) == a)
                cout << "--> " << a << endl;

        if(bar(1) == 1)
                cout << "-->" << 1 << endl;

        return 0;
}
